package com.zhenai.jmeter;

import org.apache.commons.lang.StringUtils;

/**
 * 方法签名工具类，用于转换 服务测试/服务Mock 中的方法签名 与 方法名/方法参数列表
 *
 * @author xiaozi 2016年11月8日 下午4:21:00
 */
public class MethodSignatureUtils {

    /**
     * <pre>
     * 将方法定义转化成方法签名字符串，方法签名字符串的格式为：
     *
     *      方法名~参数类型1;参数类型2;参数类型3
     *
     * 无参方法的格式即为：
     *
     *      方法名
     * </pre>
     *
     * @param methodName 方法名
     * @param paramTypes 参数类型列表
     * @return
     */
    public static String convertMethod2SignatureStr(String methodName, String[] paramTypes) {
        if (methodName == null) {
            return null;
        }
        StringBuilder sb = new StringBuilder(methodName);
        sb.append("~");
        if (paramTypes != null && paramTypes.length > 0) {
            for (int i = 0; i < paramTypes.length; i++) {
                sb.append(paramTypes[i]).append(";");
            }
        }
        String result = sb.toString();

        // 若 无参，则移除 ~
        // 若 有参，则移除 最后一个 ;
        return result.substring(0, result.length() - 1);
    }

    /**
     * 获取方法签名中的参数类型列表，以字符串数组的形式返回，不做任何转换。
     *
     * @param methodSignature
     * @return
     */
    public static String[] findParameterTypes(String methodSignature) {
        if (methodSignature == null) {
            return null;
        }
        String parameterStr = StringUtils.substringAfter(methodSignature, "~");
        return StringUtils.split(parameterStr, ';');
    }

    /**
     * <pre>
     * 获取方法签名中的参数类型列表。
     *
     * 若 autoConvert 为 true，则会进行类型的自动转换，包括：
     *  1. 抹去泛型信息，例如 java.util.List<java.lang.String> 会生成为 java.util.List
     *  2. 转换内部类，例如 全类名 Xxx.Xxx 会转化成 Xxx$Xxx
     * </pre>
     *
     * @param methodSignature
     * @param autoConvert
     * @return
     */
    public static String[] findParameterTypes(String methodSignature, boolean autoConvert) {
        String[] types = findParameterTypes(methodSignature);
        if (types != null) {
            if (autoConvert) {
                for (int i = 0; i < types.length; i++) {
                    types[i] = eraseGenericType(types[i]);
                    types[i] = convertInternalClassStr(types[i]); // 处理内部类
                }
            }
        }
        return types;
    }

    /**
     * 获取方法签名中的方法名
     *
     * @param methodSignature
     * @return
     */
    public static String findMethodName(String methodSignature) {
        if (methodSignature == null) {
            return null;
        }
        return StringUtils.substringBefore(methodSignature, "~");
    }

    /**
     * 擦除 type 中的泛型信息，例如 java.util.List<java.lang.String> 会转化成 java.util.List
     *
     * @param type
     * @return
     */
    public static String eraseGenericType(String type) {
        return StringUtils.substringBefore(type, "<");
    }

    /**
     * 若 type 字符串为 Xxx.Xxx 形式表示的内部类，则转化成 Xxx$Xxx 表示的形式。
     *
     * @param type
     * @return
     */
    public static String convertInternalClassStr(String type) {
        String[] subs = type.split("\\.");
        if (subs.length < 2 || !Character.isUpperCase(subs[subs.length - 2].charAt(0))) {
            return type;
        }
        String correctType = "";
        int i = 0;
        for (; i < subs.length - 1; i++) {
            correctType += subs[i] + ".";
        }
        correctType = correctType.substring(0, correctType.length() - 1);
        correctType += "$";
        correctType += subs[i];
        return correctType;
    }
}
